﻿package appLoader.dictionaries {
	
	import appLoader.data.HashTable;
	import appLoader.data.HashTable3;
	import appLoader.data.PropertyTable;
	import errors.SingletoneError;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	
	public class Dictionary extends EventDispatcher {
		
		private var _assets					:HashTable;
		private var _lang					:String;
		private var _loader					:URLLoader;
		private var _currentAsset			:LangAssetItem;
		
		private static var _allowInstance	:Boolean = true;
		private static var _singletone		:Dictionary;
		
		static public const ON_DICTIONARY_LOADED:String = "ON_DICTIONARY_LOADED";
		
		
		public function Dictionary() {
			if (_allowInstance) {
				this._assets 	= new HashTable();
				this._lang 		= "en-us";
				_allowInstance 	= false;
			} else {
				throw new SingletoneError("Erro! Tentando instanciar 'utilities.Dictionary' mais de uma vez!!!");
			}
		}
		
		static public function gett():Dictionary {
			if (_singletone == null) _singletone = new Dictionary();
			return _singletone;
		}
		
		/**
		 * Cria um idioma novo para o Dictionary gerenciar.
		 * Deve ser chamado para CADA IDIOMA antes do método 'loadXML'
		 * @param	identifyer -> chave de identificação do idioma: 'pt-br', 'en-us', 'es-es', etc.
		 * @param	nodeName -> nome do nó no XML de Dicionário associado a esse idioma
		 * @param	urlPrefix -> prefixo de url para o idioma. 'br' para português, por exemplo.
		 */
		public function createLanguage(identifyer:String, nodeName:String, urlPrefix:String):void {
			if (identifyer == null || identifyer.length == 0
				|| nodeName == null || nodeName.length == 0
				|| urlPrefix == null || urlPrefix.length == 0) {
				throw new Error("Trying create a new language asset on Dictionary with a invalid identfyer OR nodeName: " + identifyer + " " + nodeName);
			}
			var langAsset:LangAssetItem = new LangAssetItem(identifyer, nodeName, urlPrefix);
			this._assets.put(identifyer, langAsset);
		}
		
		public function loadXML(url:String):void {
			this._loader = new URLLoader();
			var req:URLRequest = new URLRequest(url);
			this._loader.addEventListener(Event.COMPLETE, buildSentences);
			this._loader.load(req);
		}
		
		private function buildSentences(e:Event):void {
			var xml:XML = XML(URLLoader(e.target).data);
			var list:XMLList = xml.f;
			var i:int = list.length();
			while (i--) {
				var no:XML = list[i];
				this.insertSentence(no.@k.toString(), no);
			}
			this.defineDefaultAsset();
			this.dispatchEvent(new Event(ON_DICTIONARY_LOADED));
		}
		
		// definir como default: ou inglês ou, se não houver, a primeira da lista:
		private function defineDefaultAsset():void {
			try {
				this._currentAsset = this._assets.get(this._lang) as LangAssetItem;
			} catch (e:Error) {
				if (this._currentAsset == null) {
					this._currentAsset = this._assets.getValueByIndex(0) as LangAssetItem;
				}
			}
		}
		
		/**
		 * As frases do sistema só podem ser acrescentadas nesse método
		 * @param	chave 	-> chave para acesso da frase
		 */
		private function insertSentence(key:String, no:XML):void {
			// recebida a chave, percorrer os idiomas disponibilizados nos nós:
			var list:XMLList = no.children();
			var tt:int = list.length();
			for (var i:int = 0; i < tt; i++) {
				var noI:XML = list[i];
				var assetI:LangAssetItem = this.getAssetByNodeName(noI.name());
				if (assetI == null) {
					throw new Error("It was not found a LangAssetItem associated with the XML node name ", noI.name());
				}
				assetI.dictio.put(key, noI.toString());
			}
		}
		
		private function getAssetByNodeName(name:String):LangAssetItem {
			var tt:int = this._assets.length();
			for (var i:int = 0; i < tt; i++) {
				var ass:LangAssetItem = this._assets.getValueByIndex(i) as LangAssetItem;
				if (ass.xmlNodeName == name) return ass;
			}
			return null;
		}
		
		public function getText(key:String):String {
			return this._currentAsset.dictio.getStringProperty(key);
		}
		
		public function get lang():String { return _lang; }
		public function set lang(value:String):void {
			_lang = value;
			this._currentAsset = this._assets.get(value) as LangAssetItem;
		}
		
		public function get currentAsset():LangAssetItem { return _currentAsset; }
		
		public function getCurrentURLPrefix():String {
			return this._currentAsset.urlPrefix;
		}
		
	}
	
}
